#include "Uniform.h"
#include "Uniform.h"
#include "Uniform.h"

namespace Horse {

	IUniform::IUniform(const QString& name)
		: m_name(name)
	{
	}

	IUniform::~IUniform()
	{
	}

	QString IUniform::getName() const
	{
		return m_name;
	}


	QColorUniform::QColorUniform(const QString& name)
		: IUniform(name)
	{
	}
	QColorUniform& QColorUniform::operator=(const QColor& color)
	{
		m_color = color;
		return *this;
	}

	QColorUniform* QColorUniform::clone()
	{
		QColorUniform* uniform = new QColorUniform(m_name);
		uniform->m_color = QColor(m_color.red(), m_color.green(), m_color.blue(), m_color.alpha());
		return uniform;
	}

	void QColorUniform::useUniform(QOpenGLShaderProgram* shaderProgram)
	{
		shaderProgram->setUniformValue(m_name.toLocal8Bit(), m_color);
	}

	IntUniform::IntUniform(const QString& name)
		: IUniform(name)
		, m_value(0)
	{
	}

	IntUniform& IntUniform::operator=(int value)
	{
		m_value = value;
		return *this;
	}

	IntUniform* IntUniform::clone()
	{
		IntUniform* uniform = new IntUniform(m_name);
		uniform->m_value = m_value;
		return uniform;
	}

	void IntUniform::useUniform(QOpenGLShaderProgram* shaderProgram)
	{
		shaderProgram->setUniformValue(m_name.toLocal8Bit(), m_value);
	}

	FloatUniform::FloatUniform(const QString& name)
		: IUniform(name)
		, m_value(0.0f)
	{
	}

	FloatUniform& FloatUniform::operator=(float value)
	{
		m_value = value;
		return *this;
	}

	FloatUniform* FloatUniform::clone()
	{
		FloatUniform* uniform = new FloatUniform(m_name);
		uniform->m_value = m_value;
		return uniform;
	}

	void FloatUniform::useUniform(QOpenGLShaderProgram* shaderProgram)
	{
		shaderProgram->setUniformValue(m_name.toLocal8Bit(), m_value);
	}

	QVector2DUniform::QVector2DUniform(const QString& name)
		: IUniform(name)
	{
	}

	QVector2DUniform& QVector2DUniform::operator=(const QVector2D& vector2D)
	{
		m_vector2D = vector2D;
		return *this;
	}

	QVector2DUniform* QVector2DUniform::clone()
	{
		QVector2DUniform* uniform = new QVector2DUniform(m_name);
		uniform->m_vector2D = QVector2D(m_vector2D.x(), m_vector2D.y());
		return uniform;
	}

	void QVector2DUniform::useUniform(QOpenGLShaderProgram* shaderProgram)
	{
		shaderProgram->setUniformValue(m_name.toLocal8Bit(), m_vector2D);
	}

	QVector3DUniform::QVector3DUniform(const QString& name)
		: IUniform(name)
	{
	}

	QVector3DUniform& QVector3DUniform::operator=(const QVector3D& vector3D)
	{
		m_vector3D = vector3D;
		return *this;
	}

	QVector3DUniform* QVector3DUniform::clone()
	{
		QVector3DUniform* uniform = new QVector3DUniform(m_name);
		uniform->m_vector3D = QVector3D(m_vector3D.x(), m_vector3D.y(), m_vector3D.z());
		return uniform;
	}

	void QVector3DUniform::useUniform(QOpenGLShaderProgram* shaderProgram)
	{
		shaderProgram->setUniformValue(m_name.toLocal8Bit(), m_vector3D);
	}

	QVector4DUniform::QVector4DUniform(const QString& name)
		: IUniform(name)
	{
	}

	QVector4DUniform& QVector4DUniform::operator=(const QVector4D& vector4D)
	{
		m_vector4D = vector4D;
		return *this;
	}

	QVector4DUniform* QVector4DUniform::clone()
	{
		QVector4DUniform* uniform = new QVector4DUniform(m_name);
		uniform->m_vector4D = m_vector4D;
		return uniform;
	}

	void QVector4DUniform::useUniform(QOpenGLShaderProgram* shaderProgram)
	{
		shaderProgram->setUniformValue(m_name.toLocal8Bit(), m_vector4D);
	}

	QMatrix3x3Uniform::QMatrix3x3Uniform(const QString& name)
		: IUniform(name)
	{
	}

	QMatrix3x3Uniform& QMatrix3x3Uniform::operator=(const QMatrix3x3& matrix3x3)
	{
		m_matrix3x3 = matrix3x3;
		return *this;
	}

	QMatrix3x3Uniform* QMatrix3x3Uniform::clone()
	{
		QMatrix3x3Uniform* uniform = new QMatrix3x3Uniform(m_name);
		uniform->m_matrix3x3 = m_matrix3x3;
		return uniform;
	}

	void QMatrix3x3Uniform::useUniform(QOpenGLShaderProgram* shaderProgram)
	{
		shaderProgram->setUniformValue(m_name.toLocal8Bit(), m_matrix3x3);
	}


	QMatrix4x4Uniform::QMatrix4x4Uniform(const QString& name)
		: IUniform(name)
	{
	}

	QMatrix4x4Uniform& QMatrix4x4Uniform::operator=(const QMatrix4x4& matrix4x4)
	{
		m_matrix4x4 = matrix4x4;
		return *this;
	}

	QMatrix4x4Uniform* QMatrix4x4Uniform::clone()
	{
		QMatrix4x4Uniform* uniform = new QMatrix4x4Uniform(m_name);
		//uniform->m_color = QColor(m_color.red(), m_color.green(), m_color.blue(), m_color.alpha());
		return uniform;
	}
	void QMatrix4x4Uniform::useUniform(QOpenGLShaderProgram* shaderProgram)
	{
		shaderProgram->setUniformValue(m_name.toLocal8Bit(), m_matrix4x4);
	}

	TextureUniform::TextureUniform(const QString& name)
		: IUniform(name)
		, m_unit(0)
		, m_texture(nullptr)
	{
	}

	TextureUniform& TextureUniform::operator=(const ITexture* texture)
	{
		m_texture = const_cast<ITexture*>(texture);
		return *this;
	}

	TextureUniform& TextureUniform::operator=(unsigned int unit)
	{
		m_unit = unit;
		return *this;
	}

	TextureUniform* TextureUniform::clone()
	{
		TextureUniform* uniform = new TextureUniform(m_name);
		uniform->m_texture = m_texture;
		return uniform;
	}

	void TextureUniform::useUniform(QOpenGLShaderProgram* shaderProgram)
	{
		shaderProgram->setUniformValue(m_name.toLocal8Bit(), m_unit);
		m_texture->useTexture(m_unit);
	}

}
